package io.gitee.milklynk;

import com.alibaba.fastjson2.*;
import com.alibaba.fastjson2.filter.PropertyFilter;
import io.gitee.milklynk.vo.enums.Uri;
import io.gitee.milklynk.vo.request.ChatRequest;
import io.gitee.milklynk.vo.request.Message;
import io.gitee.milklynk.vo.response.ChatResponse;
import io.gitee.milklynk.vo.response.Choice;
import lombok.SneakyThrows;
import okhttp3.*;
import org.jetbrains.annotations.NotNull;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;

public class DeepSeek {
    private final String baseUrl;
    private final String apiKey ;
    private final OkHttpClient httpClient;


    public DeepSeek(String apiKey,String baseUrl,long timeout,TimeUnit unit){
        this.apiKey = apiKey;
        this.baseUrl = baseUrl;
        httpClient= new OkHttpClient.Builder()
                .pingInterval(10, TimeUnit.SECONDS)
                .connectTimeout(timeout, unit)
                .callTimeout(timeout,unit)
                .readTimeout(timeout,unit)
                .writeTimeout(timeout,unit)
                .build();
    }
    public DeepSeek(String apiKey,String baseUrl){
        this(apiKey,baseUrl,5,TimeUnit.MINUTES);
    }
    public DeepSeek(String apiKey) {
        this(apiKey, Uri.DEFAULT_BASE_URL.getUrl(),5,TimeUnit.MINUTES);
    }

    /**
     * 非流式请求，返回单个响应
     * @param chatRequest Chat请求体
     * @return Chat响应体
     */
    public ChatResponse chatCompletion(ChatRequest chatRequest) throws Exception {
        if (chatRequest.isStream()) {
            throw new IllegalArgumentException("Stream 请求必须使用 chatCompletionStream 方法");
        }
        return performRequest(chatRequest).getFirst();
    }

    /**
     * 流式请求,返回响应体列表
     * @deprecated 此方法不具备流式的意义
     * @param chatRequest Chat请求体
     * @return Chat响应体列表
     */
    @Deprecated
    public List<ChatResponse> chatCompletionStream(ChatRequest chatRequest) throws Exception {
        chatRequest.setStream(true);
        return performRequest(chatRequest);
    }

    /**
     * 流式请求,实时异步回调
     * @param chatRequest Chat请求体
     * @param callback 回调接口
     */
    public void chatCompletionStream(ChatRequest chatRequest, StreamCallback callback) {
        chatRequest.setStream(true);
        Request httpRequest = buildRequest(chatRequest);

        httpClient.newCall(httpRequest).enqueue(new Callback() {
            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) {
                Executor executor = callback.getExecutor() != null ?
                        callback.getExecutor() : Runnable::run;
                executor.execute(() -> {
                    try (response) {
                        if (!response.isSuccessful()) {
                            callback.onError(new RuntimeException("请求失败: " + response.code()));
                            return;
                        }
                        processStreamingResponse(response, callback);
                    } catch (Exception e) {
                        callback.onError(e);
                    }
                });
            }
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                callback.onError(e);
            }
        });
    }

    private List<ChatResponse> performRequest(ChatRequest request) throws Exception {
        Request httpRequest = buildRequest(request);

        try (Response response = httpClient.newCall(httpRequest).execute()) {
            if (!response.isSuccessful()) {
                throw new RuntimeException("API request failed: " + response.code() + " - " + response.body());
            }

            return request.isStream()
                    ? handleStreamResponse(response)
                    : handleNonStreamResponse(response);
        }
    }





    private Request buildRequest(ChatRequest request) {
        Set<String> messageNames = selectClassFieldNames(Message.class);;
        PropertyFilter filter = (obj, name, value) -> {
            if (obj instanceof Choice.Message message) {
                if ("reasoning_content".equals(name)) {
                    return Boolean.TRUE.equals(message.getPrefix());
                }
                return messageNames.contains(name);
            }
            return true;
        };
        String jsonRequest = JSON.toJSONString(request,filter);
        RequestBody body = RequestBody.create(jsonRequest, MediaType.get("application/json"));
        return new Request.Builder()
                .url(baseUrl + Uri.CHAT_URI.getUrl())
                .addHeader("Authorization", "Bearer " + apiKey)
                .post(body)
                .build();
    }

    private void processStreamingResponse(Response response, StreamCallback callback) throws IOException {
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(Objects.requireNonNull(response.body()).byteStream()))) {
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.startsWith("data: ")) {
                    String json = line.substring(6).trim();
                    if ("[DONE]".equals(json)) {
                        callback.onComplete();
                        break;
                    }
                    if (!json.isEmpty()) {
                        try {
                            ChatResponse chatResponse = JSON.parseObject(json, ChatResponse.class);
                            callback.onResponse(chatResponse);
                        } catch (Exception e) {
                            callback.onError(new JSONException("Failed to parse: " + json, e));
                        }
                    }
                }
            }
        }
    }

    private List<ChatResponse> handleStreamResponse(Response response) throws Exception {
        List<ChatResponse> responses = new ArrayList<>();
        processStreamingResponse(response, new StreamCallback() {
            @Override
            public void onResponse(ChatResponse response) {
                responses.add(response);
            }

            @Override
            public void onError(Exception e) {
                throw new RuntimeException("流式响应处理异常", e);
            }

            @Override
            public void onComplete() {
                // 同步处理不需要额外操作
            }
        });
        return responses;
    }

    private List<ChatResponse> handleNonStreamResponse(Response response) throws Exception {
        String jsonResponse = Objects.requireNonNull(response.body()).string();
        ChatResponse chatResponse = JSON.parseObject(jsonResponse, ChatResponse.class);
        return Collections.singletonList(chatResponse);
    }


    @SneakyThrows
    private static Set<String> selectClassFieldNames(Class<?> clazz){
        // 创建实例（需无参构造函数）
        Object instance = clazz.getDeclaredConstructor().newInstance();
        // 序列化并保留空值字段
        String jsonStr = JSON.toJSONString(instance, JSONWriter.Feature.WriteMapNullValue);
        JSONObject jsonObject = JSON.parseObject(jsonStr);
        return jsonObject.keySet();
    }
}
